home *** CD-ROM | disk | FTP | other *** search
/ CDUTIL 13 / CDUTIL #13 Julio 1995.iso / windows / acadcom / acrx / sample / tower.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-08  |  11.2 KB  |  424 lines

  1. /* Next available MSG number is  20 */
  2.  
  3. /*
  4.       
  5.    TOWER.CC
  6.  
  7.    Copyright (C) 1994 by Autodesk, Inc.
  8.  
  9.    Permission to use, copy, modify, and distribute this software in 
  10.    object code form for any purpose and without fee is hereby granted, 
  11.    provided that the above copyright notice appears in all copies and 
  12.    that both that copyright notice and the limited warranty and 
  13.    restricted rights notice below appear in all supporting 
  14.    documentation.
  15.  
  16.    AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.  
  17.    AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 
  18.    MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
  19.    DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 
  20.    UNINTERRUPTED OR ERROR FREE.
  21.  
  22.    Use, duplication, or disclosure by the U.S. Government is subject to 
  23.    restrictions set forth in FAR 52.227-19 (Commercial Computer 
  24.    Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) 
  25.    (Rights in Technical Data and Computer Software), as applicable.
  26.     
  27.    .
  28.  
  29.         Tower of Hanoi in C++ for the Rx/ADS environment
  30.  
  31.         Implemented by John Lynch   December 1988
  32.         Converted to Arx ADS by Cameron Reid  Fetbruary 11, 1994
  33.  
  34.         This is basically a translation of tower.c written by
  35.         John Lynch.
  36.  
  37.        This file implements the Tower of Hanoi problem.  It is as
  38.        specified in the rules:
  39.  
  40.           1.  Only one disc may be moved at a time.
  41.           2.  No disc may be placed on top of a smaller one.
  42.  
  43.        The only incompatibility with the original is that the universe
  44.        will not come to an end when this function completes (however, if
  45.        you run it with the specified number of discs, 64, the protons may
  46.        decay before it's done).
  47.  
  48.        One defines the tower with the command TOWER, which asks for the
  49.        number of discs.  Scaling is automatic, as is clearing away of any
  50.        previous execution.  Once the tower is defined, the solution may
  51.        be accomplished with the command SOLVE.
  52.  
  53.        The solution function, TRANSFER, is as given in Winston and Horn,
  54.        "LISP", second edition, pp. 112-114.
  55.  
  56.  
  57. */
  58.  
  59. #include <stdlib.h>
  60. #include <iostream.h>
  61. #include <string.h>
  62. #include "rxdefs.h"
  63. #include "adslib.h"
  64. #include  <stdio.h>
  65.  
  66.  
  67. #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
  68.  
  69.  
  70. /* ADS Function Table structure */
  71. typedef struct {
  72.     char    *name;
  73.     int     (*fptr)();
  74. } ftblent;
  75.  
  76.  
  77. int funcLoad   (void);
  78. int funcUnload (void);
  79. int doFun      (void);
  80.  
  81.  
  82. extern "C" {                         
  83. AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg,void * pkt);
  84. }
  85.  
  86. /* Local functions */
  87. static int loadfuncs _((void));
  88. static int dofun _((void));
  89. static int tower2 _((void));
  90. static int solve2 _((void));
  91. #ifdef __ZTC__
  92. static int movedisc _((int from, int to));
  93. static int transfer _((int from, int to, int spare, int n));
  94. #else
  95. static int movedisc _((short from, short to));
  96. static int transfer _((short from, short to, short spare, short n));
  97. #endif
  98.  
  99.  
  100. /* Table of ADS functions */
  101. ftblent exfun[] = {
  102.         {"C:TOWER2", tower2},
  103.         {"C:SOLVE2", solve2},
  104. };
  105.  
  106. /* For convenience, make the global variables the same as in the LISP
  107.    version */
  108.  
  109. int nrings = 0,                       /* Number of rings */
  110.     before = 0,                       /* Whether or not we have run before */
  111.     armed = 0;                        /* Set if we are ready to solve */
  112.  
  113. ads_real bthick = 1.0,                /* Base thickness */
  114.          rthick = 1.0,                /* Ring thickness */
  115.          smring = 1.5,                /* Smallest ring */
  116.          ringinc = 1.0,               /* Ring size increment */
  117.          postdia = 0.5,               /* Post diameter */
  118.          airspace = 0.1,              /* Airspace */
  119.          rspace = 1.1,                /* Total ring space */
  120.          postposx[3],
  121.          postposy;
  122.  
  123.  
  124. /* The postlist structure is used to hold the disks */
  125. struct disk {
  126.      struct disk *next;
  127.      short color;
  128.      ads_real r;
  129.      ads_name diskname;
  130. } *disks;
  131.  
  132. struct postlist {
  133.      struct disk *top;
  134.      short count;
  135. } postl[3];
  136.  
  137. /* to keep track of stuff for cleanup */
  138.  
  139. /* funcLoad  --  Register (or define) external functions with AutoLISP */
  140. int
  141. funcLoad()
  142. {
  143.     if (!ads_defun(/*MSG0*/"C:TOWER2", 0))        /* tower2 command has id 0 */
  144.         return 0;
  145.     if (!ads_defun(/*MSG0*/"C:SOLVE2", 1))        /* solve2 command has id 1 */
  146.         return 0;
  147.  
  148.     ads_printf(/*MSG17*/"\
  149. Use tower2 to initialize, and solve2 to solve the tower\n");
  150.  
  151.     return 1;
  152. }
  153.  
  154.  
  155. /* Handle setup of tower */
  156.  
  157. static int
  158. tower2()
  159. {
  160.     ads_real lring;                   /* largest ring diameter */
  161.     int a, i;
  162.     ads_real bwidth, blength;         /* width and length of base */
  163.     ads_real x, y, z, r;
  164.     struct resbuf genrb;
  165.     ads_point pt1, pt2, pt3, pt4;
  166.     struct resbuf *bufp;
  167.     ads_name ename;
  168.     short color;
  169.  
  170.     bthick = rthick = ringinc = postdia = 1.0;
  171.     smring = 1.5;
  172.     airspace = 0.1;
  173.     rspace = 1.1;
  174.  
  175.     /* Disallow null, zero and negative responses.  */
  176.     ads_initget(7, NULL);
  177.     ads_getint(/*MSG18*/"Enter number of rings: ", &nrings);
  178.  
  179.     lring = smring + (nrings * ringinc);
  180.  
  181.     /* reset from possible previous run */
  182.     postl[0].top   = postl[1].top   = postl[2].top = NULL;
  183.     postl[0].count = postl[1].count = postl[2].count = 0;
  184.  
  185.     disks = (struct disk *) malloc ((nrings + 1) * (sizeof (struct disk)));
  186.  
  187.     rspace = rthick + airspace;       /* Actual ring spacing */
  188.  
  189.     /* set up the appropriate environment variables */
  190.     genrb.restype = RTSHORT;
  191.     genrb.resval.rint = 0;
  192.     ads_setvar(/*MSG0*/"blipmode", &genrb);
  193.     ads_setvar(/*MSG0*/"cmdecho", &genrb);
  194.     ads_setvar(/*MSG0*/"fillmode", &genrb);
  195.     color = 0;
  196.     
  197.     if (before) {
  198.         // TBD
  199.         // ads_setview(origin);
  200.         while (ads_entlast( ename) == RTNORM) 
  201.         ads_entdel( ename);
  202.     } 
  203.     
  204.     /* Draw the base */
  205.     bwidth = lring + 2 * postdia;
  206.     blength = 3 * (postdia + lring) + postdia;
  207.     pt1[X] = pt1[Y] = 0.0;
  208.     pt2[Y] = pt4[Y] = bwidth;
  209.     pt3[X] = pt4[X] = blength;
  210.     pt2[X] = pt3[Y] = 0.0;
  211.     bufp = ads_buildlist( RTDXF0, "SOLID", 62, color, 39, bthick,
  212.             10, pt1, 11, pt2, 12, pt3, 13, pt4, 0);
  213.     ads_entmake(bufp);
  214.  
  215.     /* Draw the posts */
  216.     x = postdia + lring;
  217.     y = lring / 2 + postdia;
  218.     postposx[0] = y;
  219.     postposx[1] = y + x;
  220.     postposx[2] = y + x + x;
  221.  
  222.     postposy = postdia + lring / 2;
  223.  
  224.     pt1[Y] = postposy;
  225.     
  226.     for (i = 0; i < 3; i++) {
  227.         pt1[X] = postposx[i];
  228.         bufp = ads_buildlist( RTDXF0, "CIRCLE", 62, color, 
  229.                 39, (nrings + 1) * rspace, 
  230.                 10, pt1, 40, postdia, 0);
  231.         ads_entmake(bufp);
  232.     }
  233.     bthick += airspace;               /* Offset position of lowest ring */
  234.  
  235.     // TBD 
  236.     // ads_setview( oneoneone);
  237.  
  238.     /* Draw the rings, placing them on the first post initially */
  239.     pt1[X] = y;
  240.     pt1[Y] = postposy;
  241.  
  242.     a = 6;
  243.     z = bthick;
  244.     r = lring / 2;
  245.     for (i = 1; i <= nrings; i++) {      
  246.      pt1[Z] = z;
  247.     disks[i].color = a%6+1;
  248.  
  249.     bufp = ads_buildlist( RTDXF0, "CIRCLE", 62, disks[i].color,
  250.                 39, rthick, 10, pt1,  40, r,  0);
  251.     ads_entmake(bufp);
  252.     ads_entlast(disks[i].diskname);
  253.  
  254.         /* Hang it on the postlist */
  255.         disks[i].r = r;
  256.         disks[i].next = postl[0].top;
  257.  
  258.         postl[0].top = &disks[i];
  259.         postl[0].count++;
  260.  
  261.         r -= ringinc / 2;
  262.         z += rspace;
  263.         a++;
  264.     }
  265.  
  266.     before = nrings + 4;
  267.  
  268.     genrb.restype = RTSHORT;
  269.     genrb.resval.rint = 0;
  270.     ads_setvar(/*MSG0*/"cmdecho", &genrb);
  271.  
  272.     armed = TRUE;
  273.     ads_retvoid();
  274.  
  275.     return TRUE;
  276. }
  277.  
  278. /* Solve the tower problem. */
  279. static int
  280. solve2()
  281. {
  282.     if (!armed) {
  283.         ads_printf(/*MSG19*/"You must tower2 before solving\n");
  284.         return TRUE;
  285.     } else
  286.         armed = FALSE;
  287.  
  288.     transfer(1, 2, 3, nrings);
  289.     ads_redraw(NULL, 0);
  290.     ads_retvoid();
  291.     return  TRUE;
  292. }
  293.  
  294. static int
  295. movedisc(short from, short to)
  296. {
  297.     struct disk *lfrom, *lto;
  298.     ads_point pt;
  299.     ads_name ename;
  300.     resbuf *bufp;
  301.  
  302.     /* Get the current heads of the to and from lists */
  303.     lfrom = postl[from - 1].top;
  304.     lto = postl[to - 1].top;
  305.  
  306.     /* Remove this disk from the head of the from list */
  307.     postl[from - 1].top = lfrom->next;
  308.     postl[from - 1].count--;
  309.  
  310.     /* Remove this disk from the drawing */
  311.     ads_entdel( lfrom->diskname);
  312.  
  313.     pt[X] = postposx[to - 1];
  314.     pt[Y] = postposy;
  315.     pt[Z] = bthick + postl[to-1].count * rspace;
  316.     bufp = ads_buildlist( RTDXF0, "CIRCLE", 62, lfrom->color, 39, rthick,
  317.             10, pt, 40, lfrom->r, 0);
  318.     ads_entmake( bufp);
  319.     ads_entlast( lfrom->diskname);
  320.     
  321.     /* Place the disk on the top of the to list */
  322.     lfrom->next = lto;
  323.     postl[to - 1].top = lfrom;
  324.     postl[to - 1].count++;
  325.  
  326.     return TRUE;
  327. }
  328.  
  329.  
  330. static int transfer(short from, short to, short spare, short n)
  331. {
  332.     if (n == 0)
  333.         return TRUE;
  334.     else if (n == 1)
  335.         movedisc(from, to);
  336.     else {
  337.         transfer(from, spare, to, n - 1);
  338.         movedisc(from, to);
  339.         transfer(spare, to, from, n - 1);
  340.     }
  341.     return TRUE;
  342. }
  343.  
  344.  
  345. /******************************************************************************/
  346. /*.doc funclUnload(internal) */
  347. /*+
  348.     This function is called to undefine all function names in the ADS
  349.     function table.  Each named function will be removed from the
  350.     AutoLISP hash table.
  351. -*/
  352. /******************************************************************************/
  353. int
  354. /*FCN*/funcUnload()
  355. {
  356.     int i;
  357.  
  358.     /* Undefine each function we defined */
  359.  
  360.     for (i = 0; i < ELEMENTS(exfun); i++) {
  361.         ads_undef(exfun[i].name,i);
  362.     }
  363.  
  364.     return RTNORM;
  365. }
  366.  
  367. /******************************************************************************/
  368. /*.doc doFun(internal) */
  369. /*+
  370.     This function is called to invoke the function which has the
  371.     registerd function code that is obtained from  ads_getfuncode.  The
  372.     function will return RTERROR if the function code is invalid, or
  373.     RSERR if the invoked function fails to return RTNORM.  The value
  374.     RSRSLT will be returned if the function code is valid and the
  375.     invoked subroutine returns RTNORM.
  376. -*/
  377. /******************************************************************************/
  378. int
  379. /*FCN*/doFun()
  380. {
  381.     int    val;
  382.     int    rc;
  383.  
  384.     ads_retvoid();
  385.         
  386.     if ((val = ads_getfuncode()) < 0 || val > ELEMENTS(exfun))
  387.         return RTERROR;
  388.  
  389.     rc = (*exfun[val].fptr)();
  390.  
  391.     return ((rc == RTNORM) ? RSRSLT:RSERR);
  392. }
  393.  
  394.  
  395. AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void* ptr)
  396. {
  397.  
  398.     if (ptr != NULL) {
  399.         // We have been handed some kind of object
  400.         // but we aren't going to do anything with it.
  401.     }
  402.  
  403.     switch(msg) {
  404.     case AcRx::kInitAppMsg:
  405.         break;
  406.         case AcRx::kInvkSubrMsg:
  407.             doFun();
  408.             break;
  409.         case AcRx::kLoadADSMsg:
  410.             funcLoad();
  411.             break;
  412.         case AcRx::kUnloadADSMsg:
  413.             funcUnload();
  414.             ads_printf(/*MSG2*/"Unloading.\n");
  415.             break;
  416.     case AcRx::kUnloadAppMsg:
  417.         default:
  418.         break;
  419.     }
  420.     return AcRx::kRetOK;
  421. }
  422.  
  423.  
  424.